﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace SecureGRF
{
    public partial class FormEncrypt : Form
    {
        public FormEncrypt()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() != DialogResult.OK) return;
            listView1.BeginUpdate();
            foreach (string fn in openFileDialog1.FileNames)
            {
                bool isFind = false;
                foreach (ListViewItem item in listView1.Items)
                {
                    if (item.Text == fn)
                    {
                        isFind = true;
                        break;
                    }
                }
                if (!isFind)
                {
                    ListViewItem item = listView1.Items.Add(fn);
                    item.SubItems.Add("Not encrypt");
                }
            }
            listView1.EndUpdate();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            listView1.BeginUpdate();
            for (int i = listView1.SelectedItems.Count - 1; i >= 0; i--)
                listView1.Items.Remove(listView1.SelectedItems[i]);
            listView1.EndUpdate();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.SelectedPath = textBox3.Text;
            if (folderBrowserDialog1.ShowDialog() != DialogResult.OK) return;
            textBox3.Text = folderBrowserDialog1.SelectedPath;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (!CheckParameters()) return;
            List<string> inputFiles = new List<string>(listView1.Items.Count);
            List<string> outputFiles = new List<string>(listView1.Items.Count);
            foreach (ListViewItem item in listView1.Items)
            {
                inputFiles.Add(item.Text);
                outputFiles.Add(Path.Combine(textBox3.Text, Path.GetFileName(item.Text)));
            }
            EnableControl(false);
            DoEncryptDelegate doEncrypt = new DoEncryptDelegate(DoEncrypt);
            doEncrypt.BeginInvoke(inputFiles.ToArray(), outputFiles.ToArray(), new AsyncCallback(DoEncryptCallback), doEncrypt);
        }

        private bool CheckParameters()
        {
            try
            {
                if (textBox1.Text.Length == 0)
                    throw new Exception("Please enter the password!");
                if (textBox2.Text.Length == 0)
                    throw new Exception("Please enter the validate password!");
                if (textBox1.Text != textBox2.Text)
                    throw new Exception("The two password are not equal!");
                if (!Directory.Exists(textBox3.Text))
                    throw new Exception("Can't find the output directory: " + textBox3.Text);
                foreach (ListViewItem item in listView1.Items)
                {
                    if (!File.Exists(item.Text))
                        throw new Exception("Can't find the GRF file: " + item.Text);
                    if (textBox3.Text.ToLower() == Path.GetDirectoryName(item.Text).ToLower())
                        throw new Exception("The GRF file's directory is the same of the output directory: " + item.Text);
                }
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return false;
            }
        }

        private delegate void DoEncryptDelegate(string[] inputFiles, string[] outputFiles);
        private void DoEncrypt(string[] inputFiles, string[] outputFiles)
        {
            SetProgress(progressBar2, inputFiles.Length, 0);
            for (int i = 0; i < inputFiles.Length; i++)
            {
                SetStatus(i, "Encrypting...");
                GRFEncrypt encrypt = new GRFEncrypt(inputFiles[i], outputFiles[i], textBox1.Text);
                encrypt.OnProgress += new GRFEncryptProgressDelegate(GRFEncryptProgress);
                string str = encrypt.DoEncrypt();
                SetStatus(i, str);
                SetProgress(progressBar2, inputFiles.Length, i + 1);
            }
        }

        private void DoEncryptCallback(IAsyncResult ar)
        {
            if (InvokeRequired)
            {
                Invoke(new AsyncCallback(DoEncryptCallback), ar);
                return;
            }
            if (ar.IsCompleted)
            {
                DoEncryptDelegate doEncrypt = (DoEncryptDelegate)ar.AsyncState;
                doEncrypt.EndInvoke(ar);
                EndEncrypt();
            }
        }

        private void GRFEncryptProgress(object sender, int count, int position)
        {
            SetProgress(progressBar1, count, position);
        }

        private delegate void SetProgressDelegate(ProgressBar pbr, int max, int value);
        private void SetProgress(ProgressBar pbr, int max, int value)
        {
            if (InvokeRequired)
            {
                Invoke(new SetProgressDelegate(SetProgress), pbr, max, value);
                return;
            }
            pbr.Maximum = max;
            pbr.Value = value;
        }

        private delegate void SetStatusDelegate(int index, string str);
        private void SetStatus(int index, string str)
        {
            if (InvokeRequired)
            {
                Invoke(new SetStatusDelegate(SetStatus), index, str);
                return;
            }
            foreach (ListViewItem it in listView1.Items) it.Selected = false;
            ListViewItem item = listView1.Items[index];
            item.Selected = true;
            item.SubItems[1].Text = str;
            listView1.EnsureVisible(index);
        }

        private void EndEncrypt()
        {
            EnableControl(true);
            MessageBox.Show("Encrypt GRF files done!", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void EnableControl(bool enabled)
        {
            button1.Enabled = enabled;
            button2.Enabled = enabled;
            textBox1.ReadOnly = !enabled;
            textBox2.ReadOnly = !enabled;
            textBox3.ReadOnly = !enabled;
            button3.Enabled = enabled;
            button4.Enabled = enabled;
        }
    }
}
